package com.corn.distribute.lock.demo.controller;

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.Serializable;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function :
 * @since : 2021/1/15 10:40
 */

@RestController
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    @Value("${server.port}")
    private String port;

    @Autowired
    private RedissonClient redissonClient;

    private final String LOCK_NAME = "MY_DISTRIBUTE_LOCK";

//    @GetMapping("/buy")
//    public String buyGoods() {
//        String lockValue = UUID.randomUUID().toString() + Thread.currentThread().getName();
//        try {
//            // 为了保证原子性 必须使用setIfAbsent + 超时时间(因为程序可能在执行到finally语句块之前挂掉,必须添加超时时间)
//            Boolean lockSuccess = redisTemplate.opsForValue().setIfAbsent(LOCK_NAME, lockValue, 10, TimeUnit.SECONDS);
//            if (lockSuccess) {
//                String goodsName = "goods:01";
//                Integer remindNo = Integer.valueOf(redisTemplate.opsForValue().get(goodsName).toString());
//                if (remindNo > 0) {
//                    redisTemplate.opsForValue().set(goodsName, remindNo - 1);
//                    return "卖出编号为: " + remindNo + "号商品 端口: " + port;
//                }
//            } else {
//                return "lock 失败..";
//            }
//        } finally {
//            // 为了保证 程序最终能释放锁 必须判断是自己的锁不能删别人的
////            if (null != redisTemplate.opsForValue().get(LOCK_NAME) && redisTemplate.opsForValue().get(LOCK_NAME).equals(lockValue)) {
////                redisTemplate.delete(LOCK_NAME);
////            }
//            final String luaScript = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
//                    "    return redis.call(\"del\",KEYS[1])\n" +
//                    "else\n" +
//                    "    return 0\n" +
//                    "end";
//            DefaultRedisScript<String> redisScript = new DefaultRedisScript<String>();
//            redisScript.setResultType(String.class);
//            RedisSerializer<String> argsSerializer = new StringRedisSerializer();
//            RedisSerializer resultSerializer = new StringRedisSerializer();
//            redisScript.setScriptSource(new ResourceScriptSource(new ByteArrayResource(luaScript.getBytes())));
//            Object result = redisTemplate.execute(redisScript, argsSerializer, resultSerializer, Collections.singletonList(LOCK_NAME), lockValue);
//            assert result != null;
//            if (result.equals(1)) {
//                System.out.println("删除锁成功!");
//            }
//        }
//        return "商品已经售完!!!";
//    }

    @GetMapping("/buy")
    public String buyGoods() {
        RLock lock = redissonClient.getLock(LOCK_NAME);
        try {
            String goodsName = "goods:01";
            Integer remindNo = Integer.valueOf(redisTemplate.opsForValue().get(goodsName).toString());
            if (remindNo > 0) {
                redisTemplate.opsForValue().set(goodsName, remindNo - 1);
                return "卖出编号为: " + remindNo + "号商品 端口: " + port;
            }
            return "商品已经售完!!!";
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}
